/*
 * Copyright (c) 2008 Sergey Rudchenko <sergey.rudchenko@gmail.com>
 * All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
 */

#include "ship.h"
#include "game.h"
#include "sprite.h"
#include "image_pool.h"
#include "controller.h"
#include "missile.h"

#include <stdlib.h>

#define SHIP_SPEED        0.2
#define SHIP_WEAPON_SPEED -0.5

struct ship* new_ship()
{
    struct ship* obj = malloc(sizeof(struct ship));
    obj->sprite = new_sprite(get_image(IMAGE_SHIP));
    obj->missiles = NULL;
    obj->max_missile_count = 1;
    obj->missile_count = 0;
    obj->fire_delay_counter.period = 5;
    obj->fire_delay_counter.value = obj->fire_delay_counter.period;
    return obj;
}

void free_ship(struct ship* obj)
{
    free(obj->sprite);
    free(obj);
}

static void ship_fire(struct ship* ship, struct game* ctx)
{
    if (counter_hit(&ship->fire_delay_counter) &&
            ship->missile_count < ship->max_missile_count)
    {
        struct missile* m = new_missile(get_image(IMAGE_MISSILE), SHIP_WEAPON_SPEED);
        sprite_move(m->sprite,
                    ship->sprite->x + ship->sprite->image->w / 2,
                    ship->sprite->y);

        ship->missiles = g_slist_append(ship->missiles, m);
        ship->fire_delay_counter.value = 0;
        ++ship->missile_count;
    }
}

int ship_update(struct ship* ship, struct game* ctx, Uint32 dticks)
{
    counter_update(&ship->fire_delay_counter);

    if (controller_check_action(ACTION_LEFT))
        ship->speed = -SHIP_SPEED;
    else if (controller_check_action(ACTION_RIGHT))
        ship->speed = SHIP_SPEED;
    else
        ship->speed = 0;

    if (ship->speed != 0)
    {
        double dx = ship->speed * dticks;
        double newx = ship->sprite->x + dx;
        if (newx >= 0 && newx + ship->sprite->image->w < ctx->area.w)
            sprite_move(ship->sprite, dx, 0);
    }

    GSList* entry = ship->missiles;

    while (entry)
    {
        struct missile* m = entry->data;
        if (!missile_update(m, ctx, dticks))
        {
            GSList* next = g_slist_next(entry);
            free_missile(m);
            ship->missiles = g_slist_delete_link(ship->missiles, entry);
            --ship->missile_count;
            entry = next;
        }
        else
            entry = g_slist_next(entry);
    }

    if (controller_check_action(ACTION_FIRE))
        ship_fire(ship, ctx);

    return 0;
}

void ship_blit(struct ship* ship, struct game* ctx, SDL_Surface* bg)
{
    GSList* entry = ship->missiles;

    while (entry)
    {
        struct missile* missile = entry->data;
        sprite_blit(missile->sprite, ctx->screen, bg);
        entry = g_slist_next(entry);
    }

    sprite_blit(ship->sprite, ctx->screen, bg);
}

